//随机森林分类

//添加矢量边界
function addMyLayer()
{
  var empty = ee.Image().toByte();
  var outline = empty.paint({
    featureCollection:HarbinShp, // 行政边界命名为fc
    color:0, //颜色透明
    width:1 //边界宽度
  });
  Map.addLayer(outline, {palette: "ff0000"}, "outline");
}

addMyLayer();

/*
  在边界内选点标记
    water: 1; road: 2; buliding: 3, cropland: 4; forest: 5;
  开启卫星地图模式进行选取，每个至少选60个以上
*/

//哨兵2号去云处理
function maskS2clouds(image)
{
  var qa = image.select('QA60');
  // Bits 10 and 11 are clouds and cirrus, respectively.
  var cloudBitMask = 1 << 10;
  var cirrusBitMask = 1 << 11;

  // Both flags should be set to zero, indicating clear conditions.
  var mask = qa.bitwiseAnd(cloudBitMask).eq(0)
      .and(qa.bitwiseAnd(cirrusBitMask).eq(0));

  return image.updateMask(mask).divide(10000);
}

//Build the Sentinel 2 collection, filtered by date, bounds and percentage of cloud cover 
var dataset = ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
                  .filterDate('2022-01-01','2022-12-31')
                  .filterBounds(HarbinShp)
                  .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE',10))
                  .map(maskS2clouds);
print("Sentinel 2 Image Collection",dataset);


var dem = ee.Image("NASA/NASADEM_HGT/001");

// Construct Classfication Dataset
// RS Index Cacluate(NDVI\NDWI\EVI\BSI)
var add_RS_index = function(img){
  var ndvi = img.normalizedDifference(['B8', 'B4']).rename('NDVI').copyProperties(img,['system:time_start']);
  var ndwi = img.normalizedDifference(['B3', 'B8']).rename('NDWI').copyProperties(img,['system:time_start']);
  var evi = img.expression('2.5 * ((NIR - RED) / (NIR + 6 * RED - 7.5 * BLUE + 1))', 
  {
    'NIR': img.select('B8'),
    'RED': img.select('B4'),
    'BLUE': img.select('B2')
  }).rename('EVI').copyProperties(img,['system:time_start']);
  var bsi = img.expression('((RED + SWIR1) - (NIR + BLUE)) / ((RED + SWIR1) + (NIR + BLUE)) ', 
  {
    'RED': img.select('B4'), 
    'BLUE': img.select('B2'),
    'NIR': img.select('B8'),
    'SWIR1': img.select('B11'),

  }).rename('BSI').copyProperties(img,['system:time_start']);
  var ibi = img.expression('(2 * SWIR1 / (SWIR1 + NIR) - (NIR / (NIR + RED) + GREEN / (GREEN + SWIR1))) / (2 * SWIR1 / (SWIR1 + NIR) + (NIR / (NIR + RED) + GREEN / (GREEN + SWIR1)))', {
    'SWIR1': img.select('B11'),
    'NIR': img.select('B8'),
    'RED': img.select('B4'),
    'GREEN': img.select('B3')
  }).rename('IBI').copyProperties(img,['system:time_start']);
  return img.addBands([ndvi, ndwi, evi, bsi, ibi]);
};

var dataset = dataset.map(add_RS_index); 
var bands = ['B2','B3','B4','B5','B6','B7','B8','B8A','B11','NDVI','NDWI','BSI'];
var imgcol_median = dataset.select(bands).median();
var Harbin_dem = dem.select('elevation').clip(HarbinShp).rename('DEM');
var construct_img = imgcol_median.addBands(Harbin_dem).clip(HarbinShp);

//分类样本
var train_points = Cropland.merge(Building).merge(Road).merge(Forest).merge(Water);
var train_data= construct_img.sampleRegions({
  collection: train_points,
  properties: ['landcover'],
  scale: 10
});

//精度评价
var withRandom = train_data.randomColumn('random');//样本点随机的排列
var split = 0.7; 
var trainingPartition = withRandom.filter(ee.Filter.lt('random', split));//筛选70%的样本作为训练样本
var testingPartition = withRandom.filter(ee.Filter.gte('random', split));//筛选30%的样本作为测试样本

//分类方法选择随机森林
var rf = ee.Classifier.smileRandomForest({
  numberOfTrees: 20,  
  bagFraction: 0.8
}).train({
  features: train_data,
  classProperty: 'landcover',
  // inputProperties: inputbands
});
//对哨兵数据进行随机森林分类
var img_classfication = construct_img.classify(rf); 

//运用测试样本分类，确定要进行函数运算的数据集以及函数
var test = testingPartition.classify(rf);
//计算混淆矩阵
var confusionMatrix = test.errorMatrix('landcover', 'classification');
print('confusionMatrix',confusionMatrix);//面板上显示混淆矩阵
print('overall accuracy', confusionMatrix.accuracy());//面板上显示总体精度
print('kappa accuracy', confusionMatrix.kappa());//面板上显示kappa值
Map.centerObject(HarbinShp);
Map.addLayer(HarbinShp);
Map.addLayer(img_classfication.clip(HarbinShp), {min: 1, max: 4, palette: ['red', 'orange', 'green','blue']});
var class1=img_classfication.clip(HarbinShp);

//导出分类图
Export.image.toDrive({  
       image: class1,  
       description: 'rfclass',  
       fileNamePrefix: 'rf',  //文件命名
       folder: "class",  //保存的文件夹
       scale: 10,  //分辨率
       region: HarbinShp,  //研究区
       maxPixels: 1e13,  //最大像元素，默认就好
       crs: "EPSG:4326"  //设置投影
   });  